package com.hc.concurrent_likes.service.impl;

import com.hc.concurrent_likes.entity.*;
import com.hc.concurrent_likes.event.MoodProducer;
import com.hc.concurrent_likes.mapper.MoodMapper;
import com.hc.concurrent_likes.mapper.UserMapper;
import com.hc.concurrent_likes.mapper.UserMoodPraiseRelMapper;
import com.hc.concurrent_likes.service.MoodService;
import com.hc.concurrent_likes.service.UserService;
import com.hc.concurrent_likes.utils.ConcurrentLikesConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service("moodService")
public class MoodServiceImpl implements MoodService, ConcurrentLikesConstant {

    @Autowired
    @Qualifier("moodMapper")
    private MoodMapper moodMapper;

    @Autowired
    @Qualifier("userMapper")
    private UserMapper userMapper;

    @Autowired
    @Qualifier("userMoodPraiseRelMapper")
    private UserMoodPraiseRelMapper userMoodPraiseRelMapper;

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    @Qualifier("userService")
    private UserService userService;

    @Resource
    private MoodProducer moodProducer;

    private static Integer count = 0;

    @Override
    public List<MoodDTO> findAll() {
        //查看所有说说
        List<Mood> moods = moodMapper.findAll();
        return converModel2DTO(moods);
    }

    /**
     * 将集合中的Mood转化为MoodDTO
     * @param moodList Mood类的集合
     * @return MoodDTO类的集合
     */
    private List<MoodDTO> converModel2DTO(List<Mood> moodList){
        if(CollectionUtils.isEmpty(moodList))
            return Collections.EMPTY_LIST;

        List<MoodDTO> moodDTOList = new ArrayList<>();
        for (Mood mood : moodList) {
            MoodDTO moodDTO = new MoodDTO();
            moodDTO.setId(mood.getId());
            moodDTO.setContent(mood.getContent());
            moodDTO.setPraiseNum(mood.getPraiseNum());
            moodDTO.setPublishTime(mood.getPublishTime());
            moodDTO.setUserId(mood.getUserId());
            moodDTOList.add(moodDTO);

            User user = userMapper.findById(mood.getUserId());
            userMapper.findById(mood.getId());
            moodDTO.setUsername(user.getName());
            moodDTO.setUserAccount(user.getAccount());
        }
        return moodDTOList;
    }

    @Override
    public int update(Mood mood) {
        return moodMapper.update(mood);
    }

    @Override
    public boolean praiseMood(String userId, String moodId) {
        //保存关联关系
        UserMoodPraiseRel userMoodPraiseRel = new UserMoodPraiseRel();
        userMoodPraiseRel.setUserId(userId);
        userMoodPraiseRel.setMoodId(moodId);
        userMoodPraiseRelMapper.save(userMoodPraiseRel);

        //更新说说的点赞数量
        Mood mood = this.findById(moodId);
        mood.setPraiseNum(mood.getPraiseNum() + 1);
        this.update(mood);
        return Boolean.TRUE;
    }

    @Override
    public Mood findById(String id) {
        return moodMapper.findById(id);
    }

    @Override
    public boolean praiseMoodForRedis(String userId, String moodId) {
        //采用分布式事务的方式
        MoodDTO moodDTO = new MoodDTO();
        moodDTO.setId(moodId);
        moodDTO.setUserId(userId);
        Event event = new Event();
        event.setTopic(TOPIC_LIKES);
        event.setMoodDTO(moodDTO);

        //异步进行点赞
        moodProducer.frieMoodEvent(event);


//        redisTemplate.execute(new SessionCallback(){
//            @Override
//            public Object execute(RedisOperations operations) throws DataAccessException {
//                //开启事务
//                operations.multi();
//
//                //存放到set集合中，key为PRAISE_HASH_KEY，value为moodId
//                redisTemplate.opsForSet().add(PRAISE_HASH_KEY, moodId);
//
//                //存放到set集合中，key为moodId，value为userId
//                //多个用户给一条说说点赞
//                redisTemplate.opsForSet().add(moodId, userId);
//                //点赞数+1（模拟直播时用户可不停地点赞）
////                redisTemplate.opsForValue().set(PRAISE_COUNT_KEY, ++count);
//                return operations.exec();//执行事务并提交
//            }
//        });

        return true;
    }

    @Override
    public List<MoodDTO> findAllForRedis() {
        List<Mood> moods = moodMapper.findAll();

        if (CollectionUtils.isEmpty(moods))
            return Collections.EMPTY_LIST;

        List<MoodDTO> moodDTOS = new ArrayList<>();
        //将Mood转化成MoodDTO，传入到集合中
        for (Mood mood : moods) {
            MoodDTO moodDTO = new MoodDTO();
            moodDTO.setId(mood.getId());
            moodDTO.setUserId(mood.getUserId());

//            System.out.println("说说实例：" + mood);
//            System.out.println("moodId" + mood.getId());
//            System.out.println("userId" + mood.getUserId());

            //总点赞数量：数据库的点赞数量 + redis的点赞数量
            /*
             * 出现
             * WRONGTYPE Operation against a key holding the wrong kind of value
             * 出现这个错误的原因是这个key可能是不同类型的key
             * 例如：同一个key，这个key可能是set类型，也可能是hash类型
             * 解决方式：清空一次缓存
             */
//            redisTemplate.delete(mood.getId());

            moodDTO.setPraiseNum(mood.getPraiseNum()
                    + redisTemplate.opsForSet().size(mood.getId()).intValue());
//            moodDTO.setPraiseNum(mood.getPraiseNum() +
//                    (Integer)redisTemplate.opsForValue().get(PRAISE_COUNT_KEY));

            moodDTO.setPublishTime(mood.getPublishTime());
            moodDTO.setContent(mood.getContent());
            //通过userId查询用户（UserDTO继承了User）
            User user = userService.find(mood.getUserId());
            //用户名
            moodDTO.setUsername(user.getName());
            //账户
            moodDTO.setUserAccount(user.getAccount());
            moodDTOS.add(moodDTO);
        }
        return moodDTOS;
    }
}
